package sketchpad.business.function.impl;

import org.json.JSONArray;
import org.json.JSONObject;
import sketchpad.constant.Auth;
import sketchpad.constant.CHNName;
import sketchpad.constant.Geometry;
import sketchpad.constant.SketchPadException;
import sketchpad.gui.control.DrawControl;
import sketchpad.gui.drawinggraph.DrawItem;
import sketchpad.gui.drawinggraph.node.Node;
import sketchpad.business.function.dto.UpLoadImgReturnDTO;
import sketchpad.business.function.LabelService;

import javax.imageio.ImageIO;
import javax.swing.filechooser.FileSystemView;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;
import java.util.Iterator;

public final class LabelServiceImpl implements LabelService {
    private DrawControl drawControl;

    public LabelServiceImpl(DrawControl control){
        drawControl = control;
    }

    @Override
    public void label(String name) {
        if (drawControl.getIsSelect() && !drawControl.getSelectedItemList().isEmpty()){
            Geometry geometry = Geometry.RANDOM;
            switch (name){
                case CHNName.CIRCLE:geometry=Geometry.CIRCLE;break;
                case CHNName.RECTANGLE:geometry=Geometry.RECTANGLE;break;
                case CHNName.TRIANGLE:geometry=Geometry.TRIANGLE;break;
                default:
            }
            SketchPadException exception = drawControl.getCalcHelperServiceImpl().fixDrawItem(geometry);
            if (exception!=SketchPadException.NO_LOGIC_EXCEPTION){throw new RuntimeException(exception.toString());}
        }
    }

    @Override
    public UpLoadImgReturnDTO recognize() {
        DrawItem selectBox = drawControl.getLastSelectBox();
        if (selectBox==null)return null;
        try {
            captureImg(selectBox.getLeftUpNode(), selectBox.getRightDownNode());
            String imgBase64Str = picToBase64();
            if (imgBase64Str.equals(""))throw new Exception("图片没有正确转换");
            UpLoadImgReturnDTO dto =  connectServer(imgBase64Str, 0);
            deleteImg();
            return dto;
        } catch (Exception e) {
            System.out.println("捕获照片出错");
        }
        return null;
    }

    private File file;

    private void captureImg(Node leftUpNode, Node rightDownNode) throws Exception {
        Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
        BufferedImage image = new Robot().createScreenCapture(new Rectangle(0,0,dimension.width, dimension.height));
        double x1 = leftUpNode.x + drawControl.getStage().getX()+10;
        double y1 = leftUpNode.y + drawControl.getStage().getY()+100;
        double x2 = rightDownNode.x + drawControl.getStage().getX()+10;
        double y2 = rightDownNode.y + drawControl.getStage().getY()+100;
        BufferedImage upLoadImage = image.getSubimage((int)Math.min(x1,x2),(int)Math.min(y1,y2),(int)Math.abs(x1-x2),(int)Math.abs(y1-y2));
        File path = FileSystemView.getFileSystemView().getHomeDirectory();
        file = new File(path + File.separator + "upLoadImg.jpg");
        ImageIO.write(upLoadImage, "jpg",file);
    }

    private UpLoadImgReturnDTO connectServer(String imgBase64Str, int cnt){
        if (cnt>3)return null;//防止死循环
        String requestHost = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/classification/imageclassification"
                + "?access_token=" + Auth.ACCESS_TOKEN;
        try {
            URL url = new URL(requestHost);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type","application/json");
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.connect();
            OutputStream os = connection.getOutputStream();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("image",imgBase64Str);
            jsonObject.put("top_num",3);
            os.write(jsonObject.toString().getBytes());
            os.flush();
            os.close();
            // 定义 BufferedReader输入流来读取URL的响应
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String result = "";
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            in.close();
            jsonObject = new JSONObject(result);
            JSONArray jsonArray = jsonObject.getJSONArray("results");
            Iterator<Object> iterator = jsonArray.iterator();
            String maxName = "";
            double max = Double.MIN_VALUE;
            while (iterator.hasNext()){
                JSONObject object = (JSONObject) iterator.next();
                String name = object.getString("name");
                double tmp = object.getDouble("score");
                if (tmp>max){
                    maxName = name;
                    max = tmp;
                }
            }
            return new UpLoadImgReturnDTO(maxName,max);
        } catch (Exception e) {
            //e.printStackTrace();
            getAuth();
            return connectServer(imgBase64Str,cnt+1);
        }
    }

    private void deleteImg(){
        file.deleteOnExit();
    }

    private String picToBase64(){
        File pic = new File(FileSystemView.getFileSystemView().getHomeDirectory()+File.separator+"upLoadImg.jpg");
        String base64PicStr = "";
        if (file.exists()){
            try(FileInputStream fis = new FileInputStream(pic)) {
                byte[] bytes = new byte[(int)pic.length()];
                fis.read(bytes);
                byte[] base64Pic = Base64.getEncoder().encode(bytes);
                base64PicStr = new String(base64Pic);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return base64PicStr;
    }

    /**
     * 获取API访问token
     * 该token有一定的有效期，需要自行管理，当失效时需重新获取.
     * @return assess_token 示例：
     * "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567"
     */
    private void getAuth() {
        // 获取token地址
        String authHost = "https://aip.baidubce.com/oauth/2.0/token?";
        String getAccessTokenUrl = authHost
                // 1. grant_type为固定参数
                + "grant_type=client_credentials"
                // 2. 官网获取的 API Key
                + "&client_id=" + Auth.API_KEY
                // 3. 官网获取的 Secret Key
                + "&client_secret=" + Auth.SECRET_KEY;
        try {
            URL realUrl = new URL(getAccessTokenUrl);
            // 打开和URL之间的连接
            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            // 定义 BufferedReader输入流来读取URL的响应
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String result = "";
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            JSONObject jsonObject = new JSONObject(result);
            String access_token = jsonObject.getString("access_token");
            Auth.ACCESS_TOKEN = access_token;
        } catch (Exception e) {
            System.err.printf("获取token失败！");
            e.printStackTrace(System.err);
        }
    }
}
